Vue.js中的8种组件间的通信方式;3个组件实例是前6种通信的实例,组件直接复制粘贴即可看到运行结果

您所在的位置:网站首页 vue reject provide Vue.js中的8种组件间的通信方式;3个组件实例是前6种通信的实例,组件直接复制粘贴即可看到运行结果

Vue.js中的8种组件间的通信方式;3个组件实例是前6种通信的实例,组件直接复制粘贴即可看到运行结果

#Vue.js中的8种组件间的通信方式;3个组件实例是前6种通信的实例,组件直接复制粘贴即可看到运行结果| 来源: 网络整理| 查看: 265

文章目录 一、$children / $parent 二、props / $emit 三、eventBus 四、ref 五、provide / reject 六、$attrs / $listeners 七、localStorage / sessionStorage 八、Vuex 实例以element ui为例。例子从上往下逐渐变复杂(后面例子没有删前面的无用代码,有时间重新整理一下!)

一、$children / $parent

在这里插入图片描述

拿到 $children / $parent 即可访问子 / 父 组件的所有变量和方法。 官方说 $children / $parent 仅作为应急的通信方法,其中一个原因就是 $children / $parent仅代表的是根组件下的第一个子/父vue组件(普通html标签不含有vue实例,不包含在内),当位置变化或者之间需要增加新的组件,对应的指向就变了,如以下例子。 一般用在组件简单且不易改变的情形,单独把子组件放在根组件的下一级。 使用实例(复制粘贴即可跑起来看效果): // 子组件 // 1.创建子组件 我是子组件,父组件的数据:{ { parentMsg}} export default { data() { return { msg: "children", parentMsg:"" }; }, mounted(){ console.log(this.$parent) this.parentMsg = this.$parent.msg } }; // 父组件 我是父组件,子组件的数据:{ { childrenMsg}} // 2.引入 import pCom from "./pCom"; export default { components: { pCom }, // 3.挂载 data() { return { msg: "parent", childrenMsg: "" }; }, mounted() { console.log(this.$children) this.childrenMsg = this.$children[0].msg; } };

两个vue文件放在同一目录下即可运行。 中间需要间插入el组件时,父子关系变为子孙,获取数据失败:

// 父组件模板改为此 我是父组件,子组件的数据:{ { childrenMsg}}

然而插入非element组件(即html标签),则父子关系不变:

// 父组件模板改为此 我是父组件,子组件的数据:{ { childrenMsg}} 二、props / $emit

官方推荐的父子关系通信方式,不用在乎层级关系,而且没有多余数据传输,父组件给什么,子组件就拿什么、用什么。(原理也是监听和广播,后第三种方式一样,只不过这是局部的,别忘了@是v-on的省略)。props应该也可以放函数地址然后子组件调用,如果可以的话也可以替代emit(待测)。 父组件:

父组件: 我是父组件,我自己拿的子组件数据:{ { childrenMsg}} 点我出弹框 子组件主动给我更新的数据:{ { childrenMsg2}} 子组件: // 2.引入 import pCom from "./pCom"; export default { components: { pCom }, // 3.挂载 data() { return { msg: "parent", childrenMsg: "", childrenMsg2: "" }; }, methods: { alertBox(flag) { alert(`调用了${ flag ? "自己" : "爸爸"}的弹框`); }, setMsg(msg) { this.childrenMsg2 = msg; } }, mounted() { console.log(this.$children); this.childrenMsg = this.$children[1].msg; } };

子组件:

我是子组件,我自己拿的父组件数据:{ { parentMsg}} 爸爸用props传给我的信息:{ { parentMsg2}} (备注:{ { memo}}) 点我出弹框,并且修改爸爸的数据 export default { props: ["parentMsg2", "memo"], data() { return { msg: "children", parentMsg: "" }; }, methods: { useParentMethods() { this.$emit("alertBox", false); this.$emit("setParentMsg", `看你还嚣张! ${ Date().split(' ')[4]}`); } }, mounted() { console.log(this.$parent); this.parentMsg = this.$parent.msg; } }; 三、eventBus

监听和广播: 优点:使用简单,导入即用。 缺点:阅读性差,因为你只能打印出这个bus(vue实例),看到所有的监听事件,但并不知道事件谁用了,在哪用的,用来干什么,所以仅适合小规模开发,非父子组件交互较少场景,仅用来处理非父子组件间的通信。 使用: 1.封装一个bus model下新建eventBus.js(一般是这个目录) 在这里插入图片描述 内容

import Vue from 'vue' var EmitData = new Vue(); export default EmitData; // 暴露一个vue实例,统一监听、广播所有事件

2.父组件导入并且监听(非父子组件也如此)

父组件: 我是父组件,我自己拿的子组件数据:{ { childrenMsg}} 点我出弹框 子组件主动给我更新的数据:{ { childrenMsg2}} 广播更新时间:{ { time}} 子组件: // 2.引入 import pCom from "./pCom"; import eventBus from "@/model/eventBus.js"; export default { components: { pCom }, // 3.挂载 data() { return { msg: "parent", childrenMsg: "", childrenMsg2: "", time: "" }; }, methods: { alertBox(flag) { alert(`调用了${ flag ? "自己" : "爸爸"}的弹框`); }, setMsg(msg) { this.childrenMsg2 = msg; } }, mounted() { console.log(this.$children); this.childrenMsg = this.$children[1].msg; eventBus.$on("updateTime", time => { this.time = time; }); } };

3.子组件导入并且广播(触发事件)(非父子组件也如此)

我是子组件,我自己拿的父组件数据:{ { parentMsg}} 爸爸用props传给我的信息:{ { parentMsg2}} (备注:{ { memo}}) 点我出弹框,并且修改爸爸的数据 点我更新时间 import eventBus from "@/model/eventBus.js"; export default { props: ["parentMsg2", "memo"], data() { return { msg: "children", parentMsg: "" }; }, methods: { useParentMethods() { this.$emit("alertBox", false); this.$emit("setParentMsg", `看你还嚣张! ${ Date().split(' ')[4]}`); }, updateParentTime(){ eventBus.$emit("updateTime",Date().split(' ')[4]) } }, mounted() { console.log(this.$parent); this.parentMsg = this.$parent.msg; } };

移除监听:

eventBus.$off('updateTime', { }) 四、ref

如果在普通的 DOM 元素上使用ref,引用指向的就是 DOM 元素;如果用在element组件上,引用就指向组件vue实例,可以通过实例直接调用组件的方法、数据或 DOM 元素。 所以ref是单向的,父操作子的数据和方法。 使用: 给子组件注入ref=“xx”,之后xx就是这个子组件的实例了(在this.$refs.xx调用时要注意他是最后加载的,一般为了确保加载完成可以使用setTimeout或者this.$nextTick(()=>{this.$refs.xx})) 子组件不用变,父组件增加ref

父组件: 我是父组件,我自己拿的子组件数据:{ { childrenMsg}} 点我出弹框 子组件主动给我更新的数据:{ { childrenMsg2}} 广播更新时间:{ { time}} 点我使用refs拿子组件数据和方法 子组件: // 2.引入 import pCom from "./pCom"; import eventBus from "@/model/eventBus.js"; export default { components: { pCom }, // 3.挂载 data() { return { msg: "parent", childrenMsg: "", childrenMsg2: "", time: "" }; }, methods: { alertBox(flag) { alert(`调用了${ flag ? "自己" : "爸爸"}的弹框`); }, setMsg(msg) { this.childrenMsg2 = msg; }, getChild(){ alert("子组件msg:"+this.$refs.pCom.msg+" ;并且更新自己的时间") this.$refs.pCom.updateParentTime() } }, mounted() { console.log(this.$children); this.childrenMsg = this.$children[1].msg; eventBus.$on("updateTime", time => { this.time = time; }); } }; 五、provide / reject

provide/ inject 是vue2.2.0新增的api,在组件多层嵌套的时候,根组件只要通过provide来提供变量, 然后任意子组件(孙组件、重孙等等)中通过inject来注入变量(注入this中)即可拿到根组件数据、方法。不局限于只能从当前父组件的props属性中获取数据、方法。由此可知,provide / reject是单向的,只提供子孙等组件获取根组件数据、方法。 父组件:

父组件: 我是父组件,我自己拿的子组件数据:{ { childrenMsg}} 点我出弹框 子组件主动给我更新的数据:{ { childrenMsg2}} 广播更新时间:{ { time}} 点我使用refs拿子组件数据和方法 子组件: // 2.引入 import pCom from "./pCom"; import eventBus from "@/model/eventBus.js"; export default { components: { pCom }, // 3.挂载 data() { return { msg: "parent", childrenMsg: "", childrenMsg2: "", time: "" }; }, provide() { return { rootMsg: this.msg, rootAlertBox: this.alertBox }; }, methods: { alertBox(flag) { alert(`调用了${ flag ? "自己" : "爸爸"}的弹框`); }, setMsg(msg) { this.childrenMsg2 = msg; }, getChild() { alert("子组件msg:" + this.$refs.pCom.msg + " ;并且更新自己的时间"); this.$refs.pCom.updateParentTime(); } }, mounted() { console.log(this.$children); this.childrenMsg = this.$children[1].msg; eventBus.$on("updateTime", time => { this.time = time; }); } };

子组件:

我是子组件,我自己拿的父组件数据:{ { parentMsg}} 爸爸用props传给我的信息:{ { parentMsg2}} (备注:{ { memo}}) 点我出弹框,并且修改爸爸的数据 点我更新时间 点我看看provide / reject有没有获取到 import eventBus from "@/model/eventBus.js"; export default { props: ["parentMsg2", "memo"], data() { return { msg: "children", parentMsg: "" }; }, inject: { rootMsg: { default: "获取根组件数据失败" }, rootAlertBox: { default: () => { return "获取根组件函数失败"; } } }, methods: { useParentMethods() { this.$emit("alertBox", false); this.$emit("setParentMsg", `看你还嚣张! ${ Date().split(" ")[4]}`); }, updateParentTime() { eventBus.$emit("updateTime", Date().split(" ")[4]); }, userPJ(){ alert(this.rootMsg) this.rootAlertBox() } }, mounted() { console.log(this.$parent); this.parentMsg = this.$parent.msg; } }; 六、$attrs / $listeners

在vue2.4中,引入了$attrs 和$listeners , 新增了inheritAttrs 选项。

inheritAttrs:默认值true,继承所有的父组件属性(除props的特定绑定)作为普通的HTML特性应用在子组件的根元素上,如果你不希望组件的根元素继承特性设置inheritAttrs: false,但是class属性会继承(简单的说,inheritAttrs:true 继承除props之外的所有属性;inheritAttrs:false 只继承class属性)

$attrs–继承所有的父组件属性(除了prop传递的属性、class 和 style ),一般用在子组件的子元素上,如第一个例子的

$listeners–属性,它是一个对象,里面包含了作用在这个组件上的所有监听器,你就可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件) 实现:

1.同级创建pCom的子组件ppCom

点我调用 attrs / listeners export default { methods: { runGrand() { alert(this.$attrs.noProp); this.$listeners.alertBox(false); } }, mounted() { console.log(this.$attrs); console.log(this.$listeners); } };

2.pCom

我是子组件,我自己拿的父组件数据:{ { parentMsg}} 爸爸用props传给我的信息:{ { parentMsg2}} (备注:{ { memo}}) 点我出弹框,并且修改爸爸的数据 点我更新时间 点我看看provide / reject有没有获取到 pCom的子组件: import eventBus from "@/model/eventBus.js"; import ppCom from "./ppCom" export default { props: ["parentMsg2", "memo"], components:{ "my-ppcom":ppCom}, data() { return { msg: "children", parentMsg: "" }; }, inject: { rootMsg: { default: "获取根组件数据失败" }, rootAlertBox: { default: () => { return "获取根组件函数失败"; } } }, methods: { useParentMethods() { this.$emit("alertBox", false); this.$emit("setParentMsg", `看你还嚣张! ${ Date().split(" ")[4]}`); }, updateParentTime() { eventBus.$emit("updateTime", Date().split(" ")[4]); }, userPJ(){ alert(this.rootMsg) this.rootAlertBox() } }, mounted() { console.log(this.$parent); this.parentMsg = this.$parent.msg; } };

3.父组件

父组件: 我是父组件,我自己拿的子组件数据:{ { childrenMsg}} 点我出弹框 子组件主动给我更新的数据:{ { childrenMsg2}} 广播更新时间:{ { time}} 点我使用refs拿子组件数据和方法 子组件: // 2.引入 import pCom from "./pCom"; import eventBus from "@/model/eventBus.js"; export default { components: { pCom }, // 3.挂载 data() { return { msg: "parent", childrenMsg: "", childrenMsg2: "", time: "" }; }, provide() { return { rootMsg: this.msg, rootAlertBox: this.alertBox }; }, methods: { alertBox(flag) { alert(`调用了${ flag ? "自己" : "爸爸"}的弹框`); }, setMsg(msg) { this.childrenMsg2 = msg; }, getChild() { alert("子组件msg:" + this.$refs.pCom.msg + " ;并且更新自己的时间"); this.$refs.pCom.updateParentTime(); } }, mounted() { console.log(this.$children); this.childrenMsg = this.$children[1].msg; eventBus.$on("updateTime", time => { this.time = time; }); } }; 七、localStorage / sessionStorage

通信比较简单,数据和状态比较混乱,不太容易维护。 localStorage 将数据存入浏览器,关闭浏览器再次打开仍然存在,需要手动清除; sessionStorage将数据存在对话框,关闭这个页面就没了。 他们的操作几乎是一样的,也都是js内置方法,也可以自己封装以下(我的另一篇博客有封装localStorage vue项目将token存在(vuex)store和localstorage中)。使用原生的话注意每次存入要JSON格式化,拿出要JSON解析。

localStorage 使用:

在任何地方使用 localStorage.setItem("k", JSON.stringify("v"))存入数据(方法-函数地址); 在任何地方使用 JSON.parse(localStorage.getItem("k")) 读取数据(方法-函数地址); 任何地方包括vue实例以外,因为他是原生js。 八、Vuex

数据状态管理器,适用于数据复杂、交互频繁场景,选择时要在不使用vue的困难和使用vuex的繁琐中权衡,当然啦,不管用不用都应该拿个例子来学,见我的另一篇博客 Vue使用Vuex一步步封装并使用store



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3